其他
java程序员模板设计模式真的有必要掌握下,冗余代码一扫光
程序汪公司项目实际代码中用的最频繁的设计模式就是模板设计模式了
下面就用具体代码例子去演示下模板设计模式的威力和优雅
什么场景可以用到模板模式
需要固定算法骨架
各个子类中具有公共部分
需要控制子类扩展情况,扩展留给子类
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>17.0</version>
</dependency>
代码目录
模板类
内部接口(回调关键)
请求结果基类
客户端代码
import com.google.common.base.Stopwatch;
import designpattern.template.exception.BizRuntimeException;
import java.util.concurrent.TimeUnit;
核心模板类型
这里用到的知识点有
泛型的继承
接口(入参是接口用于回调),父类引用指向子类实现
异常
这个模板类就是所谓的骨架
固定的处理逻辑在这里写好
子类(就是哪个接口留着扩展)
BizHandle这个接口可以根据自己业务具体情况增加或删除
public class CxwBizTemplate {
public <RES extends BaseResult,REQ extends BaseRequest> RES
process(RES result,
REQ request,
BizHandle bizHandle)
Stopwatch stopWatch=Stopwatch.createStarted();
try{
bizHandle.preHandle();
bizHandle.handle();
}catch (BizRuntimeException e){
//把自定义的异常码封装 result
}
catch (Exception e){
bizHandle.handleException(e,result);
System.out.println(e.getMessage());
}finally {
//记录性能日志或统一处理 result
System.out.println(bizHandle.desc()+" 耗时:"
+stopWatch.elapsed(TimeUnit.SECONDS));
}
return null;
}
public interface BizHandle<RES>{
//前置处理
void preHandle();
//具体逻辑
void handle();
//功能描述
String desc();
//异常处理
void handleException(Throwable e,RES result);
}
}
下面是请求对象和返回结果对象,
程序汪公司项目中一般都是封装一个基类
然后子类继承的
公司一般基类都是 Base开头命名
特别注意结果基类一般都会设计有异常码、异常描述的
请求基类一般都会有 requestId 用来幂等控制的
class BaseRequest{
private String requestId;
private String name;
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
};
//异常码定义在基类
class BaseResult{
private String errorDesc;
private String errorCode;
public String getErrorDesc() {
return errorDesc;
}
public void setErrorDesc(String errorDesc) {
this.errorDesc = errorDesc;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
};
客户端调用代码
匿名内部类(模板类里的接口类)
import com.google.common.base.Preconditions;
public class CxwCustomer {
public static void main(String[] args) {
CxwCustomer cxwCustomer=new CxwCustomer();
BaseRequest request=new BaseRequest();
cxwCustomer.query(request);
}
public BaseResult query(BaseRequest request){
BaseResult result=new BaseResult();
CxwBizTemplate cxwBizTemplate=new CxwBizTemplate();
cxwBizTemplate.process(result, request,
new CxwBizTemplate.BizHandle<BaseResult>() {
@Override
public void preHandle() {
Preconditions.checkNotNull(request,
"request参数空");
Preconditions.checkNotNull(request.getName(),
"request name参数空");
Preconditions.checkNotNull(request.getRequestId(),
"request RequestId参数空");
}
@Override
public void handle() {
//TODO 你的业务代码
}
@Override
public String desc() {
return "程序汪查询功能";
}
@Override
public void handleException(Throwable e, BaseResult result) {
result.setErrorDesc("程序汪查询异常");
}
});
return null;
}
}
总结
模板类就是写固定逻辑的地方
注意模板类入参有一个钩子函数,上面例子就是接口
钩子函数用于子类实现具体逻辑
使用场景
一般Controller类某功能的增删改查,程序汪公司用的比较多
rpc业务代码,程序汪手机移动端接口就是用的上面的代码
其他微服务接口业务代码
程序汪往期精彩文章包含答案
程序汪最近整理的BAT大小厂面试题2019 (面试题目录推荐)
程序汪2019的总结,认识了很多朋友赚了些小钱,现在分享出来